package com.seed.application.service.page;

import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.row.Db;
import com.mybatisflex.core.row.Row;
import com.seed.application.service.stat.StatQuery;
import com.seed.core.action.PageAction;
import com.seed.core.builder.datapermis.DataPermisBuilder;
import com.seed.core.builder.datapermis.DataPermisWrapper;
import com.seed.core.builder.declare.DeclaredWrapper;
import com.seed.core.builder.declare.QueryDeclaredBuilder;
import com.seed.core.builder.keyword.KeywordWrapper;
import com.seed.core.builder.order.OrderedBuilder;
import com.seed.core.builder.order.OrderedWrapper;
import com.seed.core.builder.query.QueryBuilder;
import com.seed.core.builder.search.SearchedBuilder;
import com.seed.core.builder.search.SearchedWrapper;
import com.seed.core.enumeration.Direction;
import com.seed.core.field.FieldContext;
import com.seed.core.listener.OnSetListener;
import com.seed.core.pojo.StatPage;
import com.seed.core.pojo.seed.Seed;
import com.seed.core.pojo.seed.Stat;
import com.seed.core.query.pojo.Declared;
import com.seed.core.query.pojo.Ordered;
import com.seed.core.query.pojo.Searched;
import com.seed.util.SeedKit;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public class PageService {
    public static final int PAGE_NUMBER = 1;
    public static final int PAGE_SIZE = 1;

    private final Seed seed; // 当前模块
    private final PageAction action; // 当前方法

    private Integer pageNumber = PAGE_NUMBER; // 当前页
    private Integer pageSize = PAGE_SIZE; // 每页大小

    private Map<String, String> searchParams; // 搜索参数
    private Map<String, Direction> orderParams; // 排序参数

    private String keyword; // 关键字
    private List<List<String>> dataPermis; // 数据权限
    private Map<String, String> fieldPermits; // 字段权限

    public PageService(Seed seed, PageAction action) {
        this.seed = seed;
        this.action = action;
    }

    public StatPage<Row> exec() {
        QueryBuilder builder = new QueryBuilder(seed);

        Map<String, Declared> declareds = new QueryDeclaredBuilder(seed, getDeclares()).build();
        if(!declareds.isEmpty()) builder.declaredWrapper(new DeclaredWrapper(seed, declareds));

        Map<String, Searched> searcheds = new SearchedBuilder(seed, getSearches(), searchParams).build();
        if(!searcheds.isEmpty()) builder.searchedWrapper(new SearchedWrapper(seed, searcheds));

        Map<String, Ordered> ordereds = new OrderedBuilder(seed, getOrders(), orderParams).build();
        if(!ordereds.isEmpty()) builder.orderedWrapper(new OrderedWrapper(seed, ordereds));

        if(StrUtil.isNotBlank(keyword)) builder.keywordWrapper(new KeywordWrapper(seed, declareds, keyword));

        List<Map<String, Searched>> dataPermised = new DataPermisBuilder(seed, dataPermis).build();
        if(!dataPermised.isEmpty()) builder.dataPermisWrapper(new DataPermisWrapper(seed, dataPermised));

        Page<Row> page = Db.paginate(null, pageNumber, pageSize, builder.build());
        List<Row> records = page.getRecords();
        if(!records.isEmpty()) {
            builder.fills(records);
            onSet(records);
            fieldPermit(records);
        }

        StatQuery statQuery = new StatQuery(seed, getStats())
                .declareds(declareds)
                .searcheds(searcheds)
                .dataPermised(dataPermised)
                .keyword(keyword);
        return new StatPage<>(page, statQuery.query());
    }

    private List<String> getDeclares() {
        // 带路径的配置
        List<String> declares = action.getDeclares();
        if(declares != null) return declares;

        declares = seed.getDeclares();
        if(declares != null) return declares;

        return SeedKit.getDefaultDeclares(seed);
    }

    private List<String> getSearches() {
        // 带路径的配置
        List<String> searched = action.getSearches();
        if(searched != null) return searched;

        searched = seed.getSearches();
        if(searched != null) return searched;

        return Collections.emptyList();
    }

    private List<String> getOrders() {
        // 带路径的配置
        List<String> orderes = action.getOrders();
        if(orderes != null) return orderes;

        orderes = seed.getOrders();
        if(orderes != null) return orderes;

        return Collections.emptyList();
    }

    private Map<String, Stat> getStats() {
        Map<String, Stat> stats = action.getStats();
        if(stats != null) return stats;

        stats = seed.getStats();
        if(stats != null) return stats;

        return Collections.emptyMap();
    }

    private void onSet(List<Row> selfList) {
        List<? extends OnSetListener> onSetListeners = SeedKit.getOnSet(seed);
        if(onSetListeners == null || onSetListeners.isEmpty()) return;

        for(Row row: selfList) {
            for(OnSetListener onSet: onSetListeners) onSet.onSet(row);
        }
    }

    private void fieldPermit(List<Row> selfList) {
        if(fieldPermits == null) return;

        for(Row entity: selfList) {
            for(Map.Entry<String, String> entry: fieldPermits.entrySet()) {
                String finalColumn = entry.getKey();
                String value = entry.getValue();
                FieldContext.auth(value, entity, finalColumn);
            }
        }
    }

    public PageService pageNumber(Integer pageNumber) {
        this.pageNumber = pageNumber;
        return this;
    }

    public PageService pageSize(Integer pageSize) {
        this.pageSize = pageSize;
        return this;
    }

    public PageService searchParams(Map<String, String> searchParams) {
        this.searchParams = searchParams;
        return this;
    }

    public PageService orderParams(Map<String, Direction> orderParams) {
        this.orderParams = orderParams;
        return this;
    }

    public PageService keyword(String keyword) {
        this.keyword = keyword;
        return this;
    }

    public PageService dataPermis(List<List<String>> dataPermis) {
        this.dataPermis = dataPermis;
        return this;
    }

    public PageService fieldPermits(Map<String, String> fieldPermits) {
        this.fieldPermits = fieldPermits;
        return this;
    }
}
